#include "fatAddress.h"

/*============================================================================
solicitaSectores()
Solicita sectores al dispositivos de almacenamiento.
En buffer se guardan todos los bytes recibidos como respuesta.
============================================================================*/
int solicitaSectores(int primerSector, int cantSectores, uint8_t * buffer,int32_t iSocketRemoto) {
	ST_NIPC		stCabecera;

	int			i, iSectorSolicitado,iRta;
	char 		szAuxiliar[600];
	uint32_t 	offset = 0;

	iSectorSolicitado = primerSector;
	// hago todos los n pedidos de sectores
	for ( i = 0; i < cantSectores ; i++ ) {
		stCabecera.ucType = GETSECTOR;
		stCabecera.lPayload = 0;
		stCabecera.sector = iSectorSolicitado;

		if( (iRta = send( iSocketRemoto, &stCabecera, sizeof(ST_NIPC), MSG_NOSIGNAL )) < 0 ){
			perror("error solicitando sector");
			close( iSocketRemoto );
			sprintf(szAuxiliar,"Al solicitar el sector %i al dispositivo de almacenamiento",iSectorSolicitado);
			loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
			return -3;
		}

		//printf("solicité el sector: %d tipo: %u size: %d socket %d\n", stCabecera.sector, stCabecera.ucType,stCabecera.lPayload,iSocketRemoto);
		//printf("COMPARACION: %i - %i\n",iRta,sizeof(ST_NIPC));

		//memset(szAuxiliar, '\0',sizeof(szAuxiliar));
		//sprintf(szAuxiliar, "Se solicito el sector: %d",stCabecera.sector);
		//loguear( "pfsLog.txt", "PFS", "INFO",szAuxiliar);

		iSectorSolicitado++;
	}

	sprintf(szAuxiliar, "Se solicito lectura desde el sector: %d hasta el sector: %d\0", primerSector, (primerSector+cantSectores));
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	// espero por la respuesta de los n sectores
	for ( i = 0; i < cantSectores ; i++ ) {
		memset(&stCabecera,'\0',sizeof(ST_NIPC));

		if( recv( iSocketRemoto, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 ) {
			perror("error recibiendo sector");
			close( iSocketRemoto );
			loguear( "pfsLog.txt", "PFS", "ERROR","Al recibir mensaje de ppd o praid");
			return -4;
		}

		//printf("recibi ST_RTA_SECTOR (sector %d) del ppd socket %d \n", stCabecera.sector, iSocketRemoto);

		//loguear( "pfsLog.txt", "PFS", "INFO","Recibi mensaje de ppd o praid");

		// armo el buffer de bytes a devolver, ubicandolo en la posicion que le corresponda, de acuerdo al nroSector recibido
		offset = (stCabecera.sector - primerSector) * SECTOR_SIZE;
		memcpy(buffer+offset, stCabecera.buffer, sizeof(ST_SECTOR));
	}

	sprintf(szAuxiliar, "Se leyo desde el sector: %d hasta el sector: %d\0", primerSector, (primerSector+cantSectores));
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	return 1;
}

/*============================================================================
escribeSectores()
============================================================================*/
int escribeSectores(int primerSector, int cantSectores, uint8_t * buffer, int32_t iSocketRemoto) {
	ST_NIPC		stCabecera;
	int			i, iSectorSolicitado;
	char 		szAuxiliar[600];

	iSectorSolicitado = primerSector;
	// hago todos los n pedidos de sectores
	for ( i = 0; i < cantSectores ; i++ ) {

		stCabecera.ucType = WRITESECTOR;
		stCabecera.sector = iSectorSolicitado;
		memcpy(stCabecera.buffer, buffer + i*SECTOR_SIZE, SECTOR_SIZE);
		stCabecera.lPayload = sizeof(ST_SECTOR);

		if( send( iSocketRemoto, &stCabecera, sizeof(ST_NIPC), MSG_NOSIGNAL ) < 0 ){
			perror("error solicitando escritura sector");
			close( iSocketRemoto );
			sprintf(szAuxiliar,"Al solicitar escritura del sector %i al dispositivo de almacenamiento",iSectorSolicitado);
			loguear( "pfsLog.txt", "PFS", "ERROR",szAuxiliar);
			return -3;
		}

		//printf("solicité escritura del sector %i: %s tipo: %u size: %d\n", stCabecera.sector, stCabecera.buffer, stCabecera.ucType, stCabecera.lPayload);

		//memset(szAuxiliar, '\0',sizeof(szAuxiliar));
		//sprintf(szAuxiliar, "Se solicito el sector: %d", stCabecera.sector);
		//loguear( "pfsLog.txt", "PFS", "INFO",szAuxiliar);

		iSectorSolicitado++;
	}

	sprintf(szAuxiliar, "Se solicito escritura desde el sector: %d hasta el sector: %d\0", primerSector, (primerSector+cantSectores));
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	// espero por la respuesta de los n sectores
	for ( i = 0; i < cantSectores ; i++ ) {
		memset(&stCabecera,'\0',sizeof(ST_NIPC));

		if( recv( iSocketRemoto, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 ) {
			perror("error recibiendo escritura");
			close( iSocketRemoto );
			loguear( "pfsLog.txt", "PFS", "ERROR","Al recibir mensaje de ppd o praid");
			return -4;
		}

		//printf("recibi ST_NIPC (sector %d) del ppd\n", stCabecera.sector);

		//loguear( "pfsLog.txt", "PFS", "INFO","Recibi mensaje de ppd o praid");

		//TODO: Chequear si recibió OK o FAIL
	}

	sprintf(szAuxiliar, "Se escribio desde el sector: %d hasta el sector: %d\0", primerSector, (primerSector+cantSectores));
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	return 1;
}


/*============================================================================
leerBloques()
Esta funcion convierte el pedido de uno o más bloques, en n pedidos asincrónicos de sectores.
============================================================================*/
int leerBloques(uint32_t primerBloque, uint32_t cantidadBloques, uint8_t * buffer, int32_t socket) {
	uint32_t sectoresPorBloque = BLOCK_SIZE / SECTOR_SIZE;
	uint32_t sectorInicial = primerBloque * sectoresPorBloque;

	solicitaSectores(sectorInicial, cantidadBloques*sectoresPorBloque, buffer, socket);
	return 1;
}

/*============================================================================
escribirBloques()
============================================================================*/
int escribirBloques(uint32_t primerBloque, uint32_t cantidadBloques, uint8_t * buffer, int32_t socket) {
	uint32_t sectoresPorBloque = BLOCK_SIZE / SECTOR_SIZE;
	uint32_t sectorInicial = primerBloque * sectoresPorBloque;

	escribeSectores(sectorInicial, cantidadBloques * sectoresPorBloque, buffer, socket);
	return 1;
}

/*============================================================================
leerCluster()
============================================================================*/
int leerCluster(uint32_t nroCluster, ST_CLUSTER buffer, int32_t socket){

	uint32_t bloquesPorCluster = CLUSTER_SIZE / BLOCK_SIZE;
	uint32_t primerCluster = (bootSector.reservedSectorCount + (uint32_t)(bootSector.numberFATs * bootSector.sectorPorFAT32))/bootSector.sectorPorCluster;
	uint32_t primerBloque = (primerCluster + nroCluster -2 ) * bloquesPorCluster ;

	leerBloques(primerBloque, bloquesPorCluster, buffer, socket);
	return 1;
}

/*============================================================================
escribirCluster()
============================================================================*/
int escribirCluster(uint32_t nroCluster, ST_CLUSTER buffer, int32_t socket){

	uint32_t bloquesPorCluster = CLUSTER_SIZE / BLOCK_SIZE;
	uint32_t primerCluster = (bootSector.reservedSectorCount + (uint32_t)(bootSector.numberFATs * bootSector.sectorPorFAT32))/bootSector.sectorPorCluster;
	uint32_t primerBloque = (primerCluster + nroCluster - 2) * bloquesPorCluster;

	escribirBloques(primerBloque, bloquesPorCluster, buffer, socket);
	return 1;
}

/*============================================================================
accederCluster()
============================================================================*/
void accederCluster( uint32_t nroCluster, ST_CLUSTER buffer, uint8_t modo, int iSocket ) {

	//int iSocket = generarSocketNuevaConexion();

	uint32_t bloquesPorCluster = CLUSTER_SIZE / BLOCK_SIZE;
	uint32_t primerCluster = (bootSector.reservedSectorCount + (uint32_t)(bootSector.numberFATs * bootSector.sectorPorFAT32))/bootSector.sectorPorCluster;
	uint32_t primerBloque = (primerCluster + nroCluster -2 ) * bloquesPorCluster ;

	if ( modo == LECTURA)
		leerBloques(primerBloque, bloquesPorCluster, buffer, iSocket);
	else
		escribirBloques(primerBloque, bloquesPorCluster, buffer, iSocket);

	//cerrarSocketNuevaConexion(iSocket);
}
